package com.mt.sdk.ble;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import com.mt.sdk.ble.model.ErroCode;
import com.mt.sdk.tools.MTTools;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothManager;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.bluetooth.BluetoothAdapter.LeScanCallback;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelUuid;

@TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
public class MTBLEManager {
	private static MTBLEManager mMTBLEManager;
	private Context context;
	public BluetoothManager mBluetoothManager;
	public BluetoothAdapter mBluetoothAdapter;

	private static final int STARTSCANEVENT = 2;
	private static final int STOPSCANEVENT = 3;
	private ScanMode scanmode;  // 扫描方式
	private UUID[] serviceUuids;
	private int worktime = 0; // 扫描时间
	private int sleeptime = 0; // 休息时间
	private int scanTimes = 0; // 扫描次数
	public Handler handl = new Handler() {
		@Override
		public void handleMessage(Message msg) {
			super.handleMessage(msg);
			if (msg.what == STARTSCANEVENT) {
				if((!isScaning()) || (!isEnable())){  // 用户停止扫描，或者已经关闭蓝牙
					return;
				}
				__startScan(scanmode, serviceUuids);
				handl.sendEmptyMessageDelayed(STOPSCANEVENT, worktime * 1000);
				return;
			}

			if (msg.what == STOPSCANEVENT) {
				if((!isScaning()) || (!isEnable())){  // 用户停止扫描，或者已经关闭蓝牙
					return;
				}
				
				__stopScan();
				if(scanTimes == -1){
					handl.sendEmptyMessageDelayed(STARTSCANEVENT, sleeptime * 1000);
					return;
				}
				scanTimes--;
				if(scanTimes == 0){ // 扫描完毕
					scan_flag = false;
					scanCallback.onScanOver(ErroCode.ERROMAP.get("OK"));
					return;
				}
				
				handl.sendEmptyMessageDelayed(STARTSCANEVENT, sleeptime * 1000);
				return;
			}
		}
	};

	private Scan5_0 mScan5_0;
	private Scan4_3 mScan4_3;

	private MTBLEManager() {
	}

	public static MTBLEManager getInstance(Context context) {
		if (mMTBLEManager == null) {

			if (android.os.Build.VERSION.SDK_INT < 18) {
				return null;
			}

			mMTBLEManager = new MTBLEManager();
			mMTBLEManager.init(context);
		}
		return mMTBLEManager;
	}

	// 初始化
	private void init(Context context) {
		this.context = context;
		this.mBluetoothManager = (BluetoothManager) context.getSystemService(Context.BLUETOOTH_SERVICE);
		this.mBluetoothAdapter = mBluetoothManager.getAdapter();

		if (android.os.Build.VERSION.SDK_INT < 21) {
			mScan4_3 = new Scan4_3(this.mBluetoothAdapter);
		} else {
			mScan5_0 = new Scan5_0(this.mBluetoothAdapter);
		}
		
		this.context.registerReceiver(mBroadcastReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));
	}
	
	// 接收广播
	private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
		@Override
		public void onReceive(Context context, Intent intent) {
			if(intent.getAction().equals(BluetoothAdapter.ACTION_STATE_CHANGED)){  // 如果是蓝牙开关变化
				
				if(!isScaning()){  // 如果不处于扫描状态，则不要做任何动作
					return;
				}

				if(intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) == BluetoothAdapter.STATE_ON){  // 开启蓝牙
					handl.sendEmptyMessageDelayed(STARTSCANEVENT, 5000);// 如果还处于扫描状态，则5秒后，继续开始扫描
					return;
				}
				
				// 关闭蓝牙
				if(intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) == BluetoothAdapter.STATE_OFF){
					__stopScan();
					handl.removeMessages(STARTSCANEVENT);
					handl.removeMessages(STOPSCANEVENT);
					if(scanTimes != -1){  // 如果不是一直扫描的话，则需要停止扫描，并且弹出错误
						scan_flag = false;
						scanCallback.onScanOver(ErroCode.ERROMAP.get("bleunable"));
					}
				}
			}
		}
	};

	// 是否可以工作
	public boolean canWork() {
		if ((mBluetoothManager == null) || (null == mBluetoothAdapter)) {
			return false;
		}
		return true;
	}

	// 开关蓝牙
	public boolean enable(boolean flag) {

		if (!canWork()) {
			return false;
		}

		if (flag) {
			mBluetoothAdapter.enable();
		} else {
			mBluetoothAdapter.disable();
		}

		return true;
	}

	// 是否使能
	public boolean isEnable() {
		if (!canWork()) {
			return false;
		}
		return mBluetoothAdapter.isEnabled();
	}

	// 获取自身mac
	public String getSelfMac() {
		if (mBluetoothAdapter == null) {
			return null;
		}
		return mBluetoothAdapter.getAddress();
	}

	// 扫描回调方法
	public interface MTScanCallback {
		public void onScan(MTBLEDevice device);

		public void onScanFail(int errocode, String erromsg);
		
		public void onScanOver(ErroCode errocode);
	}

	/*
	 * 开始扫描蓝牙(步骤:扫描worktime秒->停止扫描sleeptime秒->扫描worktime秒->停止扫描sleeptime秒………………)
	 * scanmode: 扫描方式：LOWPOWER, // 低功耗     BLANCE, // 平衡模式     FAST // 快速扫描
	 * serviceUuids: 需要过滤的UUID，如果没有则填null(建议填null)
	 * scanCallback: 扫描结果回调
	 * worktime: 扫描时间单位秒(建议填5)
	 * sleeptime: 休息时间单位秒(建议填1)
	 * scanTimes: 扫描次数(0为无限次，建议填0)
	 */
	private MTScanCallback scanCallback;
	private boolean scan_flag = false;

	public boolean startScan(ScanMode scanmode, UUID[] serviceUuids, MTScanCallback scanCallback, int worktime,
			int sleeptime, int scanTimes) {
		MTTools.logout("开始扫描");
		
		if((scanCallback == null) || (scanmode == null)){
			return false;
		}
		
		if((isScaning()) || (!mMTBLEManager.isEnable())){
			return false;
		}
		
		this.worktime = worktime;
		this.sleeptime = sleeptime;
		if(scanTimes == 0){
			this.scanTimes = -1;
		}else{
			this.scanTimes = scanTimes;
		}

		scan_flag = true;
		this.scanCallback = scanCallback;
		
		handl.sendEmptyMessage(STARTSCANEVENT);

		return true;
	}

	// 设置扫描
	private boolean pauseScan = false;
	public void pauseScan(boolean enable){
		this.pauseScan = enable;
		if(pauseScan){  // 如果需要暂停
			__stopScan();
			System.out.println("暂停扫描");
		}else{
			System.out.println("恢复扫描");
		}
	}
	
	@SuppressLint("NewApi")
	private boolean __startScan(ScanMode scanmode, UUID[] uuids) {
		if(pauseScan){   // 暂停情况下，不要实际进行扫描
			return true;
		}
		if (android.os.Build.VERSION.SDK_INT < 21) {
			mScan4_3.startScan(uuids, scanCallback);
		} else {
			mScan5_0.startScan(scanmode, uuids, scanCallback);
		}

		return true;
	}

	// 停止扫描
	public boolean stopScan() {
		MTTools.logout("停止扫描");
		if (!mMTBLEManager.isEnable()) {
			scan_flag = false;
			return false;
		}

		if (scan_flag) {
			handl.removeMessages(STARTSCANEVENT);
			handl.removeMessages(STOPSCANEVENT);
			__stopScan();
		}
		
		scan_flag = false;

		return true;
	}

	private boolean __stopScan() {
		if (android.os.Build.VERSION.SDK_INT < 21) {
			System.out.println("mScan4_3.stopScan");
			mScan4_3.stopScan();
		} else {
			mScan5_0.stopScan();
		}

		return true;
	}

	// 是否正在扫描
	public boolean isScaning() {
		return scan_flag;
	}

	// 安卓5.0+系统扫描方式
	@TargetApi(Build.VERSION_CODES.LOLLIPOP)
	private class Scan5_0 {
		private BluetoothAdapter mBluetoothAdapter;
		private MTScanCallback scanCallback;

		public Scan5_0(BluetoothAdapter mBluetoothAdapter) {
			this.mBluetoothAdapter = mBluetoothAdapter;
		}

		// 5.0+系统扫描回调方法
		private ScanCallback mScanCallback = new ScanCallback() {

			@Override
			public void onScanResult(final int callbackType, final ScanResult result) {
				super.onScanResult(callbackType, result);
				if (result == null) {
					return;
				}
				handl.post(new Runnable() {

					@Override
					public void run() {
						scanCallback.onScan(new MTBLEDevice(result.getDevice(), result.getScanRecord().getBytes(),
								result.getRssi()));
					}
				});
			}

			@Override
			public void onBatchScanResults(List<ScanResult> results) {
				super.onBatchScanResults(results);
			}

			@Override
			public void onScanFailed(int errorCode) {
				super.onScanFailed(errorCode);

				switch (errorCode) {
				case SCAN_FAILED_ALREADY_STARTED:
					scanCallback.onScanFail(1, "已经开启了扫描");
					break;
				case SCAN_FAILED_APPLICATION_REGISTRATION_FAILED:
					scanCallback.onScanFail(2, "应用程序没有注册");
					break;

				case SCAN_FAILED_FEATURE_UNSUPPORTED:
					scanCallback.onScanFail(3, "此设备不支持BLE");
					break;

				case SCAN_FAILED_INTERNAL_ERROR:
					scanCallback.onScanFail(3, "内部错误");
					break;

				default:
					scanCallback.onScanFail(0, "未知错误");
					break;
				}
			}

		};

		public boolean startScan(ScanMode scanmode, UUID[] serviceUuids, MTScanCallback scanCallback) {
			System.out.println("5.0 scan");
			
			BluetoothLeScanner scaner = mBluetoothAdapter.getBluetoothLeScanner();
			if(scaner == null){
				return false;
			}
			
			this.scanCallback = scanCallback;

			List<ScanFilter> filters = new ArrayList<ScanFilter>();
			if (serviceUuids != null) {
				for (UUID uuid2 : serviceUuids) {
					filters.add(new ScanFilter.Builder().setServiceUuid(new ParcelUuid(uuid2)).build());
				}
			}

			int model = ScanSettings.SCAN_MODE_LOW_LATENCY;
			if (scanmode == ScanMode.LOWPOWER) {
				model = ScanSettings.SCAN_MODE_LOW_POWER;
			} else if (scanmode == ScanMode.BLANCE) {
				model = ScanSettings.SCAN_MODE_BALANCED;
			} else {
				model = ScanSettings.SCAN_MODE_LOW_LATENCY;
			}

			scaner.startScan(filters, new ScanSettings.Builder().setScanMode(model).build(), mScanCallback);

			return true;
		}

		public boolean stopScan() {

			if(!isEnable()){
				return true;
			}
			
			BluetoothLeScanner scaner = mBluetoothAdapter.getBluetoothLeScanner();
			
			if(scaner == null){
				return true;
			}
			
			scaner.stopScan(mScanCallback);

			return true;
		}
	}

	// 安卓4.3+系统扫描方式
	private class Scan4_3 {
		private BluetoothAdapter mBluetoothAdapter;
		private MTScanCallback scanCallback;

		// 4.3-5.0系统扫描回调方法
		private LeScanCallback lescancallback = new LeScanCallback() {

			@Override
			public void onLeScan(final BluetoothDevice device, final int rssi, final byte[] scanRecord) {
				handl.post(new Runnable() {

					@Override
					public void run() {
						scanCallback.onScan(new MTBLEDevice(device, scanRecord, rssi));
					}
				});

				return;
			}
		};

		public Scan4_3(BluetoothAdapter mBluetoothAdapter) {
			this.mBluetoothAdapter = mBluetoothAdapter;
		}

		public boolean startScan(UUID[] serviceUuids, MTScanCallback scanCallback) {
			System.out.println("4.3 scan");
			this.scanCallback = scanCallback;
			this.mBluetoothAdapter.startLeScan(serviceUuids, lescancallback);
			return true;
		}

		public boolean stopScan() {
//			this.scanCallback = null;
			this.mBluetoothAdapter.stopLeScan(lescancallback);
			return true;
		}
	}

	public static enum ScanMode {
		LOWPOWER, // 低功耗
		BLANCE, // 平衡模式
		FAST // 快速扫描
	}

	@Override
	protected void finalize() throws Throwable {
		super.finalize();
		this.context.unregisterReceiver(mBroadcastReceiver);
	}
	
}
